
#include <Archaism/Thread.h>
#include <Windows.h>

_BeginNamespace(Radix)
/*
============================================================
== GlobalThreadProc
============================================================
*/
DWORD WINAPI GlobalThreadProc(LPVOID param)
{
	Thread* thread = static_cast<Thread*>(param);
	if(thread != nullptr)
	{
		thread->run();
	}
	return 0;
}
/*
============================================================
== Thread
============================================================
*/
struct ThreadAttribute
{
	HANDLE mHandle;
	DWORD mIdentifier;
};

void Thread::sleep(ulong ms)
{
	Sleep(ms);
}

Thread::Thread()
	:mAttribute(new ThreadAttribute)
{
	mAttribute->mHandle = 0;
	mAttribute->mIdentifier = 0;
}

Thread::~Thread()
{
	if(mAttribute->mHandle != 0)
	{
		CloseHandle(mAttribute->mHandle);
	}
	delete mAttribute;
}

void Thread::run()
{}

bool Thread::start()
{
	mAttribute->mHandle = CreateThread(
		nullptr,						// thread attribute
		0,								// initial stack size
		GlobalThreadProc,				// thread function
		this,							// thread argument
		0,								// creation option
		&(mAttribute->mIdentifier));	// thread identifier
	
	return mAttribute->mHandle != 0;
}

void Thread::stop()
{
	TerminateThread(mAttribute->mHandle, 0);
}

void Thread::suspend()
{
	SuspendThread(mAttribute->mHandle);
}

void Thread::resume()
{
	ResumeThread(mAttribute->mHandle);
}

bool Thread::isRuning()
{
	DWORD result = WaitForSingleObject(mAttribute->mHandle, 0);
	return (result == WAIT_OBJECT_0);
}

bool Thread::setPriority(int priority)
{
	return TRUE == SetThreadPriority(mAttribute->mHandle, priority);
}

int Thread::priority()
{
	return GetThreadPriority(mAttribute->mHandle);
}
/*
============================================================
== CriticalSection
============================================================
*/
struct CriticalSectionAttribute
{
	CRITICAL_SECTION mCriticalSection;
};

CriticalSection::CriticalSection()
	:mAttribute(new CriticalSectionAttribute)
{
	InitializeCriticalSection(&(mAttribute->mCriticalSection));
}

CriticalSection::~CriticalSection()
{
	DeleteCriticalSection(&(mAttribute->mCriticalSection));
	delete mAttribute;
}

bool CriticalSection::trylock()
{
	return TRUE == TryEnterCriticalSection(&(mAttribute->mCriticalSection));
}

void CriticalSection::lock()
{
	EnterCriticalSection(&(mAttribute->mCriticalSection));
}

void CriticalSection::unlock()
{
	LeaveCriticalSection(&(mAttribute->mCriticalSection));
}

/*
============================================================
== Mutex
============================================================
*/
struct MutexAttribute
{
	HANDLE mHandle;
};

Mutex::Mutex()
	:mAttribute(new MutexAttribute)
{
	mAttribute->mHandle = CreateMutex(nullptr, FALSE, nullptr);
}

Mutex::~Mutex()
{
	if(mAttribute->mHandle != 0)
	{
		CloseHandle(mAttribute->mHandle);
	}
	delete mAttribute;
}

bool Mutex::trylock(ulong ms)
{
	DWORD result = WaitForSingleObject(mAttribute->mHandle, ms);
	return result == WAIT_OBJECT_0;
}

void Mutex::lock()
{
	WaitForSingleObject(mAttribute->mHandle, INFINITE);
}

void Mutex::unlock()
{
	ReleaseMutex(mAttribute->mHandle);
}

_EndNamespace(Radix)
